#pragma once
#include "gtest/gtest.h"
#include "../../Factory/ElementCalculatorFactory.h"
#include "../ELAS1Calculator.h"

using SG::Algebra::Matrixd;
using SG::DataStructure::Common::Real;
using namespace SG::FEMSolver::Element;

// ElementCalculatorFactory 是否正确创建 Elas1 单元计算类
TEST (ElementCalculatorFactoryTest, CreateElas1Calculator)
{
    ElementCalculatorFactory::Register (ElementTypes::ELETYPE_ScalarSpring, ELAS1Calculator::Create);  

    // Test data
    const auto calculatorPtr = ElementCalculatorFactory::Create (ElementTypes::ELETYPE_ScalarSpring);
    const auto elas1CalculatorPtr = dynamic_cast<ELAS1Calculator*> (calculatorPtr.get ());

    // Check
    ASSERT_TRUE (nullptr != elas1CalculatorPtr);
}

TEST (ELAS1CalculatorTest, ComputeStiffness)
{
    // Input data
    const Real k{2.0};

    // Test data
    Matrixd kgTest (2, 2);
    ELAS1Calculator::ComputeStiffness (k, _OUT kgTest);

    // Target data
    const Matrixd kgTarget (2, 2, {2.0, -2.0, -2.0, 2.0});

    // Check
    ASSERT_TRUE (kgTarget == kgTest);
}

TEST (ELAS1CalculatorTest, DataRecoveryTest)
{
    // Input data
    const Real k{1000.0};
    const Real S{100.0};
    const Matrixd eleDisplacement (2, 1, {0.0, 2.000000E-03});

    // Test data
    Real eleInternalForceTest;
    ELAS1Calculator::ComputeElementInternalForce (k, eleDisplacement, _OUT eleInternalForceTest);
    Real eleStrainTest;
    ELAS1Calculator::ComputeElementStrain (S, eleDisplacement, _OUT eleStrainTest);
    Real eleStressTest;
    ELAS1Calculator::ComputeElementStress (S, eleInternalForceTest, _OUT eleStressTest);

    // Target data
    const Real eleInternalForceTarget{-2.000000E+00};
    const Real eleStrainTarget{-2.000000E-01};
    const Real eleStressTarget{-2.000000E+02};

    // Check
    ASSERT_TRUE (eleInternalForceTarget == eleInternalForceTest);
    ASSERT_TRUE (eleStrainTarget == eleStrainTest);
    ASSERT_TRUE (eleStressTarget == eleStressTest);
}